#include "Scene.h"
#include "Mesh.h"
#include "Camera.h"
#include "Material.h"
#include "MeshLoader.h"
#include <iostream>
#include <d3dx9.h>
#include "RenderOperation.h"

using namespace std;

Scene::Scene(int width, int height, IDirect3DDevice9* device)
	: width(width), height(height), rootNode( new Node ), device(device), renderer(device), activeCamera( 0 )
{
	ID3DXEffect *eff;
	ID3DXBuffer *errBuff;
	D3DXCreateEffectFromFileA( device, "std.fx",0,0,D3DXSHADER_DEBUG,0,&eff,&errBuff);
	if(errBuff)
		cout << (char*)errBuff->GetBufferPointer() << endl;

	stdmtrl = new Material(eff);
}

Scene::~Scene()
{
	delete rootNode;
}

Camera *Scene::CreateCamera()
{
	Camera *cam = new Camera(width, height);
	cameras.push_back(cam);
	if(activeCamera == 0)
		activeCamera = cam;
	rootNode->AddChild(cam);
	return cam;
}

Mesh *Scene::CreateMesh( MeshLoader *mload )
{
	Mesh* mesh = new Mesh( mload->GetVertices() , mload->GetIndices(), mload->GetVertexDeclaration(), stdmtrl, mload->GetStride(), mload->GetOBB(), mload->GetVertexCount(), mload->GetTriangleCount());
	meshes.push_back(mesh);
	rootNode->AddChild(mesh);
	return mesh;
}

void Scene::Render()
{
	D3DXMATRIX E;
	D3DXMatrixIdentity(&E);
	Node::BuildAbsoluteTransform( rootNode, E, true );
	
	vector<RenderOperation> rops = MakeRenderOperationList();
	
	//device->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME);
	device->SetRenderState( D3DRS_LIGHTING, false );
	device->SetRenderState( D3DRS_ZENABLE, true );
	device->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
	renderer.Draw(rops);
}

std::vector<RenderOperation> Scene::MakeRenderOperationList()
{
	vector<RenderOperation> rops;
	for( size_t i = 0; i < meshes.size(); ++i )
	{
		RenderOperation rop;
		rop.vb = meshes[i]->GetVertexBuffer();
		rop.ib = meshes[i]->GetIndexBuffer();
		rop.vdecl = meshes[i]->GetVertexDeclaration();
		rop.vertexCount = meshes[i]->CountVertices();
		rop.primCount = meshes[i]->CountTriangles();
		rop.vertexStride = meshes[i]->GetVertexStride();
		rop.mtrl = meshes[i]->GetMaterial();
		//ffp transform
		rop.model = meshes[i]->GetTransform();
		rop.view = activeCamera->GetTransform();
		rop.proj = activeCamera->GetProjection();
		//shaders
		rop.mtrl->SetValue( "world", meshes[i]->GetTransform() );
		D3DXMATRIX wvp = meshes[i]->GetTransform() * activeCamera->GetTransform() * activeCamera->GetProjection();
		rop.mtrl->SetValue( "worldViewProj", wvp );

		rops.push_back(rop);
	}
	return rops;
}